#include "handler_client.h"
#include <strings.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>    
#include <unistd.h>      
#include <fcntl.h>       
                         
int stdin_puts(int sockfd,stdin_msg_t msg){
    //判断本地有无对应文件
    char *filename = msg.value;
    if(access(filename,F_OK)==0){
        //创建文件对象
        int fd = open(filename,O_RDWR);
        if(fd == -1){
            printf("打开文件失败");
            return 2;
        }
        tlv_msg_t send_pack;
        bzero(&send_pack,sizeof(send_pack));
        //1.发送文件名给对方
        send_pack.hdr.type = CMD_PUTS_REQ;
        send_pack.hdr.length = strlen(filename);
        memcpy(send_pack.value,filename,strlen(filename));
        tlv_send(sockfd,&send_pack);
        //2.发送哈希值给服务端
        char md5_value_of_putsfile[33] = {0};
        Get_File_Md5Value(filename,md5_value_of_putsfile);
        printf("文件名:%s,md5:%s\n",filename,md5_value_of_putsfile);
        bzero(&send_pack,sizeof(send_pack));
        send_pack.hdr.type = THE_MD5_VALUE;
        send_pack.hdr.length = sizeof(md5_value_of_putsfile);
        memcpy(send_pack.value,md5_value_of_putsfile,sizeof(md5_value_of_putsfile));
        tlv_send(sockfd,&send_pack);
        //接收发过来的秒传或是直传信号
        tlv_msg_t serv_response;
        bzero(&serv_response,sizeof(serv_response));
        tlv_recv(sockfd,&serv_response);
        printf("%s\n",serv_response.value);
        if (serv_response.hdr.type==PUTS_FILE_NOEXIST){
            //--------------直传--------------------
            //发送文件长度给服务端
            struct stat file_info;
            fstat(fd,&file_info);
            off_t file_length = file_info.st_size;
            send_pack.hdr.type = DATA_CHUNK;
            send_pack.hdr.length = sizeof(file_length);
            bzero(send_pack.value,sizeof(send_pack.value));
            memcpy(send_pack.value,&file_length,sizeof(file_length));
            tlv_send(sockfd,&send_pack);
            //使用filesize和100mb长度做比较，决定接下来的文件传输的模式
            off_t limit_length = 100000000;
            //大于100mb用mmap进行传输
            if(file_length>limit_length){
                ftruncate(fd,file_length);
                char *p = (char *)mmap(NULL,file_length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
                off_t sended_size = 0;
                int send_data_once = 0;
                //int send_type = DATA_CHUNK;
                tlv_msg_t data_pack;
                //记录进度条的切片显示
                off_t record_load_pice_turn = 0;
                off_t show_load_lice = file_length/10000;
                while(sended_size<file_length){
                    send_data_once = file_length-sended_size<4096?(file_length-sended_size):4096;

                    bzero(&data_pack,sizeof(data_pack));
                    data_pack.hdr.type = DATA_CHUNK;
                    data_pack.hdr.length = send_data_once;
                    memcpy(data_pack.value, p+sended_size, send_data_once);
                    tlv_send(sockfd, &data_pack);
                    sended_size +=send_data_once;
                    if(record_load_pice_turn>show_load_lice){
                        printf("上传进度%5.2lf%%\r",100.0*sended_size/file_length);
                        fflush(stdout);
                        record_load_pice_turn = 0;
                    }else{
                        record_load_pice_turn += send_data_once;
                    }
                }
                bzero(&send_pack,sizeof(send_pack));
                send_pack.hdr.type = DATA_END;
                send_pack.hdr.length = 7;
                memcpy(send_pack.value,"bigfile",7);
                tlv_send(sockfd, &send_pack);

                munmap(p,file_length);
                close(fd);
                printf("上传进度100.00%%\n");
                //服务端反馈传输结束
                bzero(&serv_response,sizeof(serv_response));
                tlv_recv(sockfd,&serv_response);
                printf("%s\n",serv_response.value);
            }
            //小于100mb用小火车进行传输
            else{
                char buf[4096];
                tlv_msg_t send_data;
                bzero(&send_data,sizeof(send_data));
                send_data.hdr.type = DATA_CHUNK;
                off_t sended_size = 0;
                off_t record_load_pice_turn = 0;
                off_t show_load_lice = file_length/10000;
                while(sended_size<file_length){
                    bzero(buf,sizeof(buf));
                    bzero(send_data.value,sizeof(send_data.value));
                    ssize_t sret = read(fd,buf,sizeof(buf));
                    if(sret==0){
                        break;
                    }
                    send_data.hdr.length = sret;
                    memcpy(send_data.value,buf,sret);
                    tlv_send(sockfd,&send_data);
                    sended_size += sret;
                    if(record_load_pice_turn>show_load_lice){
                        printf("上传进度%5.2lf%%\r",100.0*sended_size/file_length);
                        fflush(stdout);
                        record_load_pice_turn = 0;
                    }else{
                        record_load_pice_turn += sret;
                    }
                }
                close(fd);
                printf("上传进度100.00%%\n");
                //发送文件传输结束信号
                send_data.hdr.type = DATA_END;
                send_data.hdr.length = 9;
                bzero(send_data.value,sizeof(send_data.value));
                memcpy(send_data.value,"samllfile",9);
                tlv_send(sockfd,&send_data);
                //服务端反馈传输结束
                bzero(&serv_response,sizeof(serv_response));
                tlv_recv(sockfd,&serv_response);
                printf("%s\n",serv_response.value);
            }

        }
        //--------------秒传--------------------
        else if (serv_response.hdr.type==PUTS_FILE_EXIST){
            printf("文件秒传成功\n");}
    }
    //本地没有对应文件
    else{
        printf("本地没有对应的文件对象,上传失败\n");
        return 1;
    }

    return 0;
}

int stdin_gets(int sockfd,stdin_msg_t msg){
    //发送文件名
    char *filename = msg.value;
    tlv_msg_t send_pack;
    bzero(&send_pack,sizeof(send_pack));
    tlv_create(&send_pack,CMD_GETS_REQ,strlen(filename),filename);
    tlv_send(sockfd,&send_pack);

    //接收对面是否有对应文件的反馈，根据命令码进行处理
    tlv_msg_t recv_response;
    bzero(&recv_response,sizeof(recv_response));
    tlv_recv(sockfd,&recv_response);
    //有对应文件的命令码
    if(recv_response.hdr.type==GETS_FILE_EXIST){
        //读value里面的文件总长度
        int fd = open(filename,O_RDWR|O_CREAT,0666);
        off_t file_length;
        memcpy(&file_length,recv_response.value,recv_response.hdr.length);
        printf("文件总大小为:%ld\n",file_length);
        //把文件现有 的长度发送给服务端
        struct stat file_info;
        fstat(fd,&file_info);
        //剩下的需要接收的字节长度
        off_t current_file_length = file_info.st_size;
        printf("文件现有大小为:%ld\n",current_file_length);
        bzero(&send_pack,sizeof(send_pack));
        send_pack.hdr.type = DATA_CHUNK;
        send_pack.hdr.length = sizeof(current_file_length);
        memcpy(send_pack.value,&current_file_length,send_pack.hdr.length);
        tlv_send(sockfd,&send_pack);

        lseek(fd,current_file_length,SEEK_SET);
        if(current_file_length>0){
            printf("文件开始断点续传\n");
            printf("现有进度%5.2lf%%\n",100.0*current_file_length/file_length);
        }
        //设置下载进度条打印的频次
        off_t record_load_pice_turn =0;
        off_t show_load_lice = file_length/10000;

        while(current_file_length<file_length){
            bzero(&recv_response,sizeof(recv_response));
            //每一轮接收的小火车
            tlv_recv(sockfd,&recv_response);
            //printf("length = %d\n",recv_response.hdr.length);
            if(recv_response.hdr.length!=4096){
                printf("总长:%ld,数据长度:%d\n",current_file_length,recv_response.hdr.length);
                sleep(10);
            }
            write(fd,recv_response.value,recv_response.hdr.length);
            //printf("下载成功一轮\n");
            current_file_length += recv_response.hdr.length;
            if(record_load_pice_turn>show_load_lice){
                printf("下载进度%5.2lf%%\r",100.0*current_file_length/file_length);
                fflush(stdout);
                //sleep(1);
                record_load_pice_turn = 0;
            }else{
                record_load_pice_turn += recv_response.hdr.length;
            }
        }
        //------------------------------------------------------------
        close(fd);
        printf("下载进度100.00%%\n");
        bzero(&recv_response,sizeof(recv_response));
        tlv_recv(sockfd,&recv_response);
        printf("%s\n",recv_response.value);
    }
    //服务端没有对应文件
    else if(recv_response.hdr.type==GETS_FILE_NOEXIST) {
        printf("%s\n",recv_response.value);
        return 1;
    }
    return 0;
}

